/*
   Copyright (c) 2020 Shanghai Xuanzi Technology Co. Ltd https://xuanzi.ltd
   XZUnitTest is licensed under the Mulan PSL v1.
   You can use this software according to the terms and conditions of the Mulan PSL v1.
   You may obtain a copy of Mulan PSL v1 at:
      http://license.coscl.org.cn/MulanPSL
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
   PURPOSE.
   See the Mulan PSL v1 for more details. 
 */

package xuanzi.h5.unittest;

import com.google.gwt.user.client.ui.RootPanel;

/**
 * 单元测试基类
 * 可以通过继承本类，编写单元测试，测试结果将在开发者工具的控制台显示，测试结束后请务必调用finish()方法完成本单元的测试
 * @author 彭立铭
 *
 */
public abstract class UnitTest implements Asserts.Countable{
	 
	protected String unitName;
	
	long startTime;
	
	int pass,error;
	
	public UnitTest(String name) {
		this.unitName = name;
	}
	
	/**
	 * 异常错误显示的样式
	 * @return
	 */
	protected String errorStyle() { 
		return "color:red;padding-left:0px;font-size:12px;";
	}	 
	
	/**
	 * 测试通过后显示的样式
	 * @return
	 */
	protected String passStyle() { 
		return "color:green;border-left:16px solid green;padding-left:8px;font-size:12px;";
	}

	/**
	 * 标题的样式
	 * @return
	 */
	protected String titleStyle() {
		return "color:blue;font-size:15px;border-left:24px solid blue;margin-top:36px;margin-bottom:8px";
	}
	
	/**
	 * 开始执行单元测试，并记录测试的状态
	 */
	public void start() {
		log("%c 🕷 "+unitName+"  Test Staring .. ",titleStyle()); 
		startTime = System.currentTimeMillis();
		Asserts.countables.add(this);
		doUnitTest();
	} 
	
	protected abstract void doUnitTest();

	/**
	 * 完成本单元的测试并显示结果
	 */
	public void report() {
		long time = System.currentTimeMillis()-startTime; 
		Asserts.countables.remove(this); 
		String color = (error>0?"red":"green");
		String result = error>0?(" Has "+(error)+" Errors"):" is all pass";
	 
			log(" %c [Report] "+unitName+" "+(pass+error)+" Tests "+result+". ","color:"+color+";font-size:14px;border-left:24px solid "+color);
		if(error>0)
			log(" %c ","margin-left:26px;border-left:"+(pass*5)+"px solid green;border-right:"+(error*5)+"px solid red;background:green;width:0px"); 
		log(" %c Pass : "+(pass)+" ⏱ "+time+"ms","margin-left:26px;border-left:8px solid green;"+passStyle());
		if(error>0) {
			log(" %c Error : "+(error)+" 🕷","margin-left:26px;border-left:8px solid red;"+errorStyle());
			changeTitle("Warning :"+unitName+" Tests Has Errors ,Please See Console."); 
		}
	}
	
	protected void log(String text, String css) { 
		Console.log(text, css);
	}


	public void finish() {
		report();
	}
	
	public static native void changeTitle(String title)/*-{
		$wnd.document.title = title;
		$wnd.document.body.style="border-top:5px solid red";
	}-*/;

	@Override
	public void error(String message) {
		error++;
	}
	
	@Override
	public void pass(String message) {
		pass++;
	}
	
	public static UnitTest create(String name) {
		UnitTest ut = new UnitTest(name) {
			
			@Override
			protected void doUnitTest() { 
			}
		};
		ut.start();
		return ut;
	}
	
	public static UnitTest createUI(String name) {
		UnitTest ut = new UnitTestUI(name) {
			
			@Override
			protected void doUnitTest() { 
			}
		};
		ut.start();
		return ut;
	}
	
	public native static void initNative()/*-{
	  $wnd.UnitTest = function(name,ui){
	  		var unitTest = ui?@xuanzi.h5.unittest.UnitTest::createUI(Ljava/lang/String;)(name) : @xuanzi.h5.unittest.UnitTest::create(Ljava/lang/String;)(name); 
	  		return {
	  			finish:function(){
	  				unitTest.@xuanzi.h5.unittest.UnitTest::finish()();
	  			},pageEl:function(){
	  				return unitTest.@xuanzi.h5.unittest.UnitTestUI::outEl()();
	  			}
	  		};
	  }
	}-*/;
}
